7.04. Справочник по Loki
Справочник по Loki
Loki — это система логирования, разработанная Grafana Labs, ориентированная на эффективное хранение, индексирование и запрос логов без полнотекстового поиска. Она оптимизирована для работы в связке с Prometheus и Grafana, используя те же принципы меток (labels) для организации данных. Loki не индексирует содержимое строк логов, а только их метки, что снижает потребление ресурсов и упрощает масштабирование.
Архитектура Loki
Loki состоит из нескольких компонентов, которые могут быть развернуты как отдельные микросервисы или объединены в один бинарный файл (loki или loki-simple-scalable). Основные компоненты:
Distributor
Принимает входящие логи от клиентов (например, Promtail, Fluentd, Vector).
- Валидирует структуру записей.
- Проверяет соответствие меток ограничениям.
- Распределяет потоки по ingester’ам на основе хэша меток.
- Поддерживает gRPC и HTTP интерфейсы.
Ключевые параметры:
distributor.replication_factor— количество копий каждой записи, отправляемых в разные ingester’ы (по умолчанию 3).distributor.max_recv_msg_size— максимальный размер входящего gRPC-сообщения.distributor.max_concurrent_streams— лимит одновременных потоков gRPC.
Ingester
Принимает логи от distributor’а и временно хранит их в памяти или на диске до их отправки в долговременное хранилище.
- Отвечает за сжатие, индексацию меток и создание блоков.
- Участвует в кворуме при записи (при replication_factor > 1).
- Может работать в WAL-режиме (Write-Ahead Log) для отказоустойчивости.
Ключевые параметры:
ingester.lifecycler.ring.store— тип хранилища для ring (consul, etcd, inmemory, memberlist).ingester.max_chunk_age— максимальное время жизни чанка перед флашем (по умолчанию 1 час).ingester.flush_op_timeout— таймаут операции флаша блока.ingester.wal.enabled— включение WAL для защиты от потерь при перезапуске.ingester.wal.dir— путь к директории WAL.ingester.chunk_idle_period— период неактивности чанка, после которого он флашится.
Querier
Обрабатывает запросы LogQL от пользователей или Grafana.
- Запрашивает данные у ingester’ов («hot» данные) и из хранилища («cold» данные).
- Объединяет результаты и возвращает клиенту.
- Кэширует индексы и чанки при включённом кэшировании.
Ключевые параметры:
querier.query_timeout— максимальное время выполнения запроса.querier.max_concurrent— лимит одновременных запросов.querier.ingesters_client.grpc_client_config— настройки gRPC-соединения с ingester’ами.querier.cache_results— включение кэширования результатов запросов.
Query Frontend
Опциональный компонент для ускорения и масштабирования запросов.
- Разбивает большие запросы на подзапросы по времени.
- Кэширует результаты (в Memcached, Redis и т.п.).
- Поддерживает очередь запросов и rate limiting.
Ключевые параметры:
frontend.query_range.response_cache_config— конфигурация кэша ответов.frontend.split_queries_by_interval— интервал, по которому разбиваются запросы (например,15m).frontend.max_outstanding_per_tenant— максимальное число запросов на тенант.
Compactor
Отвечает за очистку, удаление старых данных и компактизацию блоков в хранилище.
- Удаляет блоки по истечении TTL.
- Объединяет мелкие блоки для улучшения эффективности чтения.
- Работает только в режиме
boltdb-shipperилиtsdb.
Ключевые параметры:
compactor.retention_enabled— включение политики хранения.compactor.retention_delete_delay— задержка перед удалением данных после окончания срока хранения.compactor.compaction_interval— интервал запуска компактизации.compactor.block_retention— срок хранения блоков (например,744h).
Index Gateway
Используется в масштабируемых развертываниях (tsdb backend).
- Загружает индексы из объектного хранилища в память.
- Обслуживает запросы querier’а без прямого доступа к хранилищу.
- Уменьшает нагрузку на объектное хранилище.
Ключевые параметры:
index_gateway.shard_by_tenant— разделение индексов по тенантам.index_gateway.sync_dir— директория для синхронизации индексов.
Конфигурация Loki
Основной конфигурационный файл — loki.yaml. Он содержит секции для каждого компонента и общие настройки.
auth_enabled
Указывает, включена ли аутентификация по tenant ID.
- Тип: boolean
- По умолчанию:
false - При
trueкаждый запрос должен содержать заголовокX-Scope-OrgID.
server
Настройки HTTP/gRPC сервера.
http_listen_port— порт для HTTP API (по умолчанию 3100).grpc_listen_port— порт для gRPC (по умолчанию 9095).grpc_server_max_recv_msg_size— максимальный размер получаемого gRPC-сообщения.grpc_server_max_send_msg_size— максимальный размер отправляемого gRPC-сообщения.
common
Общие параметры для всех компонентов.
path_prefix— корневая директория для временных файлов.replication_factor— фактор репликации (по умолчанию 3).ring— настройки распределённого ring’а (consul/etcd/memberlist).storage— конфигурация объектного хранилища (S3, GCS, Azure, filesystem и др.).
storage_config
Определяет, где хранятся чанки и индексы.
schema
configs— список схем с указанием периода действия и типа backend’а.- Пример:
- from: "2020-10-24"
store: tsdb
object_store: s3
schema: v13
tsdb_shipper
active_index_directory— директория для активных индексов.cache_location— путь к кэшу индексов.shared_store— тип хранилища (s3,gcs,azure,filesystem).
boltdb_shipper
Устаревший, но ещё поддерживаемый backend.
active_index_directory— рабочая директория.cache_location— кэш индексов.shared_store— тип хранилища.
filesystem
Для тестовых сред.
directory— путь к директории хранения.
aws
Для S3-совместимых хранилищ.
bucketnames— имя бакета.endpoint— URL S3-совместимого сервиса.region— регион.access_key_id/secret_access_key— учётные данные.s3forcepathstyle— использовать path-style URL.
azure
container_name— имя контейнера.account_name/account_key— учётные данные.
gcs
bucket_name— имя бакета.service_account— JSON-ключ сервисного аккаунта.
LogQL — язык запросов Loki
LogQL — это язык, похожий на PromQL, но предназначенный для логов. Состоит из двух частей: selector и pipeline.
Log stream selector
Выбирает потоки логов по меткам.
{job="api"}— все логи с меткойjob="api".{cluster="prod", namespace=~"app.*"}— регулярное выражение для значения метки.{filename!~".*test.*"}— исключение по регулярному выражению.
Line filters
Фильтрация по содержимому строки.
|~ "error"— строки, содержащие "error".|= "timeout"— точное совпадение.|~ "(?i)exception"— case-insensitive через регулярное выражение.| json— парсинг JSON-строк.| logfmt— парсинг в формате logfmt.
Parser expressions
| json— автоматический парсинг JSON.| json field1, field2— выбор конкретных полей.| pattern "<ip> - - <_> \"<method> <uri> ..."— шаблонный парсинг.| regexp "(?P<ip>\\d+\\.\\d+\\.\\d+\\.\\d+).*"— регулярное выражение с именованными группами.
Metric queries
Преобразование логов в метрики.
count_over_time({job="api"}[5m])— количество строк за 5 минут.rate({job="api"}[5m])— скорость поступления строк.avg by (level) (rate({job="api"}[5m]))— агрегация по метке.
Functions
line_format "{{.message}} [{{.level}}]"— переформатирование строки.unwrap field— извлечение числового поля для метрик.label_format level=error`` — изменение метки.drop level— удаление метки.keep filename— оставить только указанные метки.
Режимы развертывания
Monolithic (single binary)
Все компоненты в одном процессе. Подходит для тестирования и небольших сред.
- Запуск:
loki -config.file=loki.yaml
Simple Scalable
Разделение на write-path и read-path.
- Write: distributor + ingester
- Read: querier + query-frontend
Microservices
Полное разделение всех компонентов. Требует внешнего координатора (Consul, Etcd, Memberlist).
Mode: TSDB
Современный режим хранения, использующий локальный TSDB-движок.
- Блоки хранятся в объектном хранилище.
- Индексы управляются через index-gateway или querier.
- Поддерживает retention и compaction.
Безопасность
Аутентификация
- Поддержка multi-tenancy через заголовок
X-Scope-OrgID. - Интеграция с OAuth2, OpenID Connect через reverse proxy (например, NGINX, Oauth2-proxy).
Шифрование
- TLS для gRPC и HTTP.
- Шифрование данных в объектном хранилище (на стороне провайдера или через KMS).
RBAC
- Управление доступом реализуется внешними средствами (Grafana Enterprise, OPA, reverse proxy).
Производительность и масштабирование
Chunk targeting
- Целевой размер чанка: ~1.5 МБ.
- Чанки флашатся при достижении размера или по таймауту.
Rate limiting
- Ограничение по tenant’ам через
rulerилиquery-frontend. - Настройки:
max_global_streams_per_user,ingestion_rate_mb.
Caching
- Индексы: Memcached, Redis.
- Результаты запросов: Memcached, in-memory.
- Конфигурация через
cacheсекции вquery_range,frontend,querier.
Retention
- Управление сроком хранения через
compactor. - Минимальный retention: 24 часа.
- Удаление происходит асинхронно с задержкой.
Клиенты и отправка логов в Loki
Loki не принимает логи напрямую от приложений — для этого используются агенты-коллекторы.
Promtail
Официальный агент от Grafana Labs.
- Читает файлы логов с диска.
- Добавляет метки на основе путей, регулярных выражений или статических значений.
- Поддерживает обнаружение новых файлов (через glob-паттерны).
- Отправляет данные в Loki через HTTP/gRPC.
- Сохраняет позицию чтения в WAL или файле состояния (
positions.yaml).
Ключевые параметры в promtail.yaml:
server.http_listen_port— порт HTTP-сервера Promtail (по умолчанию 9080).positions.filename— путь к файлу с позициями чтения.clients.url— URL Loki (например,http://loki:3100/loki/api/v1/push).scrape_configs— конфигурация источников логов.
Пример scrape_config:
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*.log
Добавление меток через pipeline:
pipeline_stages:
- regex:
expression: '^(?P<ip>\S+) - - \[(?P<timestamp>[^\]]+)\] "(?P<method>\S+) (?P<uri>\S+)'
- labels:
method:
uri:
- timestamp:
source: timestamp
format: "02/Jan/2006:15:04:05 -0700"
Fluentd / Fluent Bit
Поддерживают плагин out_loki.
- Fluent Bit легче и быстрее, подходит для edge-устройств.
- Оба позволяют парсить JSON, logfmt, регулярные выражения.
- Метки задаются через теги или фильтры.
Vector
Современный высокопроизводительный агент.
- Поддерживает преобразования, фильтрацию, маршрутизацию.
- Может отправлять в Loki, Prometheus, Elasticsearch и др.
- Конфигурация в TOML или YAML.
Пример sink в Vector:
[sinks.loki]
type = "loki"
inputs = ["app_logs"]
endpoint = "http://loki:3100"
encoding.codec = "json"
labels = { component = "web", env = "prod" }
Форматы данных в Loki
Log Entry
Структура одной записи:
- Timestamp — временная метка в наносекундах Unix.
- Line — строка лога (неиндексируемый текст).
- Labels — набор пар
key="value"(индексируются).
Пример:
{job="api", level="error"} 1700000000000000000 "Failed to connect to DB"
Chunk
Группа записей одного потока за определённый период.
- Хранится в сжатом виде (gzip, snappy, lz4).
- Имеет временные границы (
from,through). - После флаша становится неизменяемым блоком.
Index
Хранит соответствие между метками и списком чанков.
- В режиме
tsdb— это локальные TSDB-индексы. - В режиме
boltdb-shipper— BoltDB-файлы, загружаемые в память.
Метрики и мониторинг Loki
Loki экспортирует метрики в формате Prometheus. Основные группы:
Distributor
loki_distributor_received_samples_total— общее число полученных строк.loki_distributor_bytes_received_total— объём принятых данных.loki_distributor_ingester_appends_failures_total— ошибки отправки в ingester.
Ingester
loki_ingester_chunks_created_total— число созданных чанков.loki_ingester_chunks_flushed_total— число флашенных чанков.loki_ingester_memory_chunks— количество чанков в памяти.loki_ingester_memory_streams— число активных потоков.
Querier
loki_querier_store_query_duration_seconds— время запроса к хранилищу.loki_querier_lines_per_query— среднее число строк на запрос.loki_querier_queries_total— общее число запросов.
Compactor
loki_compactor_blocks_marked_for_deletion_total— блоки, помеченные на удаление.loki_compactor_blocks_cleaned_total— успешно удалённые блоки.
Рекомендуется настроить алерты на:
- Высокий уровень ошибок записи.
- Задержки флаша чанков.
- Превышение лимита памяти в ingester’ах.
- Долгие запросы (
>30 сек).
Диагностика и отладка
Проверка меток
Используйте Grafana Explore → Log browser, чтобы увидеть доступные метки и значения.
Поиск «горячих» потоков
Запрос:
count_over_time({job=~".+"}[1h])
| sort_desc
| limit 10
Проверка WAL
Если включён WAL, проверьте директорию ingester.wal.dir.
- При старте Loki восстанавливает чанки из WAL.
- Не удаляйте WAL вручную — это приведёт к потере данных.
Логирование самого Loki
Loki пишет логи в stderr. Уровень логирования задаётся через:
server:
log_level: info # debug, info, warn, error
В режиме debug видны детали распределения потоков, ошибки gRPC и т.д.
Миграция между схемами хранения
Loki использует понятие schema, определяющее формат индексов и чанков.
Поддерживаемые схемы
v9–v11— устаревшие (BoltDB, Cassandra).v12— переходный (BoltDB + объектное хранилище).v13— современный (TSDB или Shipper-based).
Как мигрировать
- Добавьте новую запись в
storage_config.schema.configsс новой датойfrom. - Запустите Loki — он будет писать новые данные по новой схеме.
- Старые данные остаются читаемыми, но не переписываются.
- Для полной миграции используйте
loki tools migrate.
Важно: нельзя менять схему задним числом. Все изменения применяются только к будущим данным.
Best Practices
Метки
- Используйте мало уникальных значений (не более 10⁵ на tenant).
- Избегайте меток с высокой кардинальностью:
user_id,request_id,trace_id. - Предпочитайте фильтрацию в LogQL, а не через метки.
Размер чанков
- Целевой размер: 1–2 МБ после сжатия.
- Настройте
chunk_target_sizeиmax_chunk_age.
Retention
- Включайте retention только в production.
- Устанавливайте
compactor.retention_delete_delay≥ 24 часов.
Безопасность
- Всегда используйте TLS между компонентами.
- Ограничивайте ingestion rate на tenant’а через
rulerили внешний прокси.
Производительность
- Используйте
query-frontendдля кэширования и шардирования запросов. - Размещайте
index-gatewayв отдельных нодах при большом объёме данных.
Пример минимальной конфигурации (monolithic)
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
path_prefix: /tmp/loki
storage:
filesystem:
directory: /tmp/loki/chunks
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
storage_config:
tsdb_shipper:
active_index_directory: /tmp/loki/tsdb-index
cache_location: /tmp/loki/tsdb-cache
shared_store: filesystem
compactor:
working_directory: /tmp/loki/compactor
compaction_interval: 10m
retention_enabled: true
retention_delete_delay: 2h
block_retention: 168h # 7 дней
Продвинутые функции LogQL
Range queries
Запросы с временным диапазоном используются для агрегации логов в метрики.
rate({job="api"}[5m])— скорость поступления строк.count_over_time({job="api"}[1h])— общее число строк за час.bytes_rate({job="api"}[10m])— объём данных в байтах в секунду.
Unwrap
Извлекает числовое значение из строки для использования в метрических функциях.
| json | unwrap duration_ms— извлекает полеduration_ms.| pattern "took <?ms>" | unwrap ms— извлекает значение из шаблона.
Label operations
label_format job=backend`` — переименовывает или задаёт значение метки.keep job, level— оставляет только указанные метки.drop filename— удаляет метку из результата.
Line format
Форматирует вывод строк:
{job="app"} | line_format "{{.message}} [{{.level}} @ {{.ts}}]"
Pipeline stages
Позволяют преобразовывать логи на лету:
regex— извлечение полей через регулярные выражения.json— парсинг JSON.logfmt— парсинг форматаkey=value.timestamp— установка временной метки из поля.labels— добавление динамических меток.match— условная обработка (например, разные пайплайны дляerrorиinfo).
Пример:
pipeline_stages:
- match:
selector: '{level="error"}'
stages:
- json:
expressions:
error_type: error.type
- labels:
error_type:
Multi-tenancy
Loki поддерживает разделение данных между тенантами через заголовок X-Scope-OrgID.
- Каждый tenant имеет своё пространство имён.
- Данные одного tenant’а недоступны другим.
- Quotas и retention могут настраиваться отдельно на tenant’а.
Включение:
auth_enabled: true
Использование:
- Все запросы и отправки должны содержать
X-Scope-OrgID: tenant-123. - Grafana передаёт этот заголовок при настройке datasource с multi-tenancy.
Управление квотами
Loki позволяет ограничивать использование ресурсов на tenant’а:
ingestion_rate_mb
Максимальный объём данных в мегабайтах в секунду.
- Пример:
ingestion_rate_mb: 10— 10 МБ/с.
ingestion_burst_size_mb
Максимальный размер всплеска (burst) при отправке.
- Пример:
ingestion_burst_size_mb: 100.
max_global_streams_per_user
Максимальное число уникальных потоков (комбинаций меток).
- Защищает от взрыва кардинальности.
Конфигурация через limits_config:
limits_config:
ingestion_rate_mb: 8
ingestion_burst_size_mb: 16
max_global_streams_per_user: 5000
Отказоустойчивость и репликация
Replication factor
- Значение ≥ 2 обеспечивает отказоустойчивость записи.
- При
replication_factor: 3данные записываются в три ingester’а. - Чтение выполняется из одного ingester’а, но при его недоступности — из реплик.
WAL (Write-Ahead Log)
- При включении (
ingester.wal.enabled: true) все входящие записи сначала пишутся на диск. - При перезапуске ingester восстанавливает чанки из WAL.
- Рекомендуется для production-сред.
Ring coordination
- Используется Consul, Etcd или memberlist для координации ingester’ов.
- Memberlist — встроенный gossip-протокол, не требует внешних зависимостей.
- Пример для memberlist:
ring:
kvstore:
store: memberlist
Резервное копирование и восстановление
Loki хранит данные в объектном хранилище, которое обычно уже имеет собственные механизмы репликации и резервного копирования. Однако для дополнительной защиты:
Backup chunks and indexes
- Просто скопируйте содержимое бакета S3/GCS/Azure.
- Индексы в режиме
tsdb— это обычные файлы, их можно архивировать.
Restore
- Остановите все компоненты Loki.
- Восстановите данные в исходное хранилище.
- Запустите Loki — он автоматически обнаружит блоки.
Point-in-time recovery
- Не поддерживается напрямую.
- Для точного восстановления используйте snapshot’ы хранилища (например, AWS S3 Object Versioning).
Интеграция с Grafana
Настройка datasource
- В Grafana: Connections → Data sources → Add data source → Loki.
- URL:
http://loki:3100. - При multi-tenancy: указать заголовок
X-Scope-OrgIDв HTTP-настройках.
Explore
- Поддержка автозаполнения меток.
- Просмотр сырых логов и метрик в одном интерфейсе.
- Возможность сохранять запросы как dashboard panels.
Alerts
- Loki не генерирует алерты напрямую.
- Используйте Grafana Alerting с LogQL-запросами:
count_over_time({job="app", level="error"}[5m]) > 10 - Алерты срабатывают при превышении порога.
Variables
- Динамические переменные на основе меток:
label_values({job=~".+"}, instance)